#include "Objects.h"
#include <cmath>
#include <GL/gl.h>

void gllibSphere(double _radius, double _divisions) {
  double ratio = M_PI/_divisions;
  double x, y, z;
  double x1, y1, z1;

  glBegin(GL_TRIANGLE_FAN);
  glNormal3f(0.0, _radius, 0.0);
  glVertex3f(0.0, _radius, 0.0);

  y = sin(M_PI/2.0 - ratio) * _radius;
  for(double alpha = M_PI*2.0; alpha >= 0.0; alpha -= ratio) {
    x = cos(alpha) * cos(M_PI/2.0 - ratio) * _radius;
    z = sin(alpha) * cos(M_PI/2.0 - ratio) * _radius;

    glNormal3f(x, y, z);
    glVertex3f(x, y, z);
  }

  glEnd();

  glBegin(GL_TRIANGLE_FAN);
  glNormal3f(0.0, -_radius, 0.0);
  glVertex3f(0.0, -_radius, 0.0);

  y = sin(-M_PI/2.0 + ratio) * _radius;
  for(double alpha = 0.0; alpha <= M_PI*2.0; alpha += ratio) {
    x = cos(alpha) * cos(-M_PI/2.0 + ratio) * _radius;
    z = sin(alpha) * cos(-M_PI/2.0 + ratio) * _radius;

    glNormal3f(x, y, z);
    glVertex3f(x, y, z);
  }
  glEnd();

  for(double beta = M_PI/2.0 - ratio; beta >= -M_PI/2.0 + ratio; beta -= ratio) {
    y = sin(beta) * _radius;
    y1 = sin(beta + -ratio) * _radius;

    glBegin(GL_QUAD_STRIP);
    for(double alpha = M_PI*2.0; alpha >= 0.0; alpha -= ratio) {
      x = cos(alpha) * cos(beta) * _radius;
      z = sin(alpha) * cos(beta) * _radius;

      x1 = cos(alpha) * cos(beta - ratio) * _radius;
      z1 = sin(alpha) * cos(beta - ratio) * _radius;

      glNormal3f(x, y, z);
      glVertex3f(x, y, z);

      glNormal3f(x1, y1, z1);
      glVertex3f(x1, y1, z1);
    }
    glEnd();
  }
}

void gllibCube(double _side) {
  double halfSide = _side/2.0;

  glBegin(GL_QUADS);
  glNormal3f(0.0, 0.0, 1.0);
  glVertex3f(-halfSide, -halfSide, halfSide);
  glVertex3f(halfSide, -halfSide, halfSide);
  glVertex3f(halfSide, halfSide, halfSide);
  glVertex3f(-halfSide, halfSide, halfSide);

  glNormal3f(0.0, 0.0, -1.0);
  glVertex3f(-halfSide, halfSide, -halfSide);
  glVertex3f(halfSide, halfSide, -halfSide);
  glVertex3f(halfSide, -halfSide, -halfSide);
  glVertex3f(-halfSide, -halfSide, -halfSide);

  glNormal3f(1.0, 0.0, 0.0);
  glVertex3f(halfSide, -halfSide, -halfSide);
  glVertex3f(halfSide, halfSide, -halfSide);
  glVertex3f(halfSide, halfSide, halfSide);
  glVertex3f(halfSide, -halfSide, halfSide);

  glNormal3f(-1.0, 0.0, 0.0);
  glVertex3f(-halfSide, -halfSide, halfSide);
  glVertex3f(-halfSide, halfSide, halfSide);
  glVertex3f(-halfSide, halfSide, -halfSide);
  glVertex3f(-halfSide, -halfSide, -halfSide);

  glNormal3f(0.0, 1.0, 0.0);
  glVertex3f(-halfSide, halfSide, -halfSide);
  glVertex3f(-halfSide, halfSide, halfSide);
  glVertex3f(halfSide, halfSide, halfSide);
  glVertex3f(halfSide, halfSide, -halfSide);

  glNormal3f(0.0, -1.0, 0.0);
  glVertex3f(halfSide, -halfSide, -halfSide);
  glVertex3f(halfSide, -halfSide, halfSide);
  glVertex3f(-halfSide, -halfSide, halfSide);
  glVertex3f(-halfSide, -halfSide, -halfSide);
  glEnd();
}

void gllibCylinder(double _radius, double _height, double _divisions) {
  double ratio = M_PI/_divisions;
  double x, y, z;

  glBegin(GL_TRIANGLE_FAN);
  glNormal3f(0.0, 1.0, 0.0);
  glVertex3f(0.0, _height/2.0, 0.0);

  y = _height/2.0;
  for(double alpha = M_PI*2.0; alpha >= 0.0; alpha -= ratio) {
    x = cos(alpha) * _radius;
    z = sin(alpha) * _radius;

    glVertex3f(x, y, z);
  }

  glEnd();

  glBegin(GL_TRIANGLE_FAN);
  glNormal3f(0.0, -1.0, 0.0);
  glVertex3f(0.0, -_height/2.0, 0.0);

  y = -_height/2.0;
  for(double alpha = 0.0; alpha <= M_PI*2.0; alpha += ratio) {
    x = cos(alpha) * _radius;
    z = sin(alpha) * _radius;

    glVertex3f(x, y, z);
  }

  glEnd();

  glBegin(GL_QUAD_STRIP);
  y = _height/2.0;
  for(double alpha = M_PI*2.0; alpha >= 0.0; alpha -= ratio) {
    x = cos(alpha) * _radius;
    z = sin(alpha) * _radius;

    glNormal3f(x, 0.0, z);
    glVertex3f(x, y, z);
    glVertex3f(x, -y, z);
  }
  glEnd();
}

void gllibCone(double _radius, double _height, double _divisions) {
  double ratio = M_PI/_divisions;
  double x, y, z;

  glBegin(GL_TRIANGLE_FAN);
  glNormal3f(0.0, _height/2.0, 0.0);
  glVertex3f(0.0, _height/2.0, 0.0);

  y = -_height/2.0;
  for(double alpha = M_PI*2.0; alpha >= 0.0; alpha -= ratio) {
    x = cos(alpha) * _radius;
    z = sin(alpha) * _radius;

    glNormal3f(x, 0.0, z);
    glVertex3f(x, y, z);
  }

  glEnd();

  glBegin(GL_TRIANGLE_FAN);
  glNormal3f(0.0, -1.0, 0.0);
  glVertex3f(0.0, -_height/2.0, 0.0);

  y = -_height/2.0;
  for(double alpha = 0.0; alpha <= M_PI*2.0; alpha += ratio) {
    x = cos(alpha) * _radius;
    z = sin(alpha) * _radius;

    glVertex3f(x, y, z);
  }

  glEnd();
}

void gllibTorus(double _inRadius, double _outRadius, double _inDivision, double _outDivision) {
  double inRatio = M_PI/_inDivision;
  double outRatio = M_PI/_outDivision;
  double x, y, z;
  double x1, y1, z1;

  for(double beta = 0.0; beta <= 2.0 * M_PI + inRatio; beta += inRatio) {
    glBegin(GL_QUAD_STRIP);
    for(double alpha = 0.0; alpha <= 2.0 * M_PI + outRatio; alpha += outRatio) {
      double cx = _outRadius * cos(alpha);
      double cz = _outRadius * sin(alpha);

      x = (_outRadius + _inRadius * cos(beta)) * cos(alpha);
      y = _inRadius * sin(beta);
      z = (_outRadius + _inRadius * cos(beta)) * sin(alpha);

      x1 = (_outRadius + _inRadius * cos(beta + inRatio)) * cos(alpha);
      y1 = _inRadius * sin(beta + inRatio);
      z1 = (_outRadius + _inRadius * cos(beta + inRatio)) * sin(alpha);

      glNormal3f(x - cx, y, z - cz);
      glVertex3f(x, y, z);

      glNormal3f(x1 - cx, y1, z1 - cz);
      glVertex3f(x1, y1, z1);
    }
    glEnd();
  }
}

void gllibCircumference(double _radius, double _division) {
  double ratio = M_PI/_division;
  double x, y;

  glBegin(GL_LINE_LOOP);

  for(double alpha = 0.0; alpha <= 2*M_PI; alpha += ratio) {
    x = cos(alpha) * _radius;
    y = sin(alpha) * _radius;

    glNormal3f(x, y, 0);
    glVertex3f(x, y, 0);
  }

  glEnd();
}
